#include "initFunc.h"
#include "utils.h"
#include "../_public.h"
#include "cmdParser.h"
#include "clog.h"
// #include "../log/log.h"
#define BUFSIZE (1024 * 8)

int initThreadControl(status_st *threadControl, pthread_t *threadIds)
{
    // 初始化队列
    void *p = initQueue();
    memcpy(&threadControl->q, p, sizeof(threadControl->q));
    // 初始化互斥锁
    pthread_mutex_init(&threadControl->mutex, NULL);
    // 初始化条件变量
    pthread_cond_init(&threadControl->cond, NULL);
    // 线程池线程数
    threadControl->threadNum = THREADNUM;
    // 设置退出标记位
    threadControl->exitFlag = 0;

    // 创建线程
    for (int i = 0; i < threadControl->threadNum; i++)
    {
        pthread_create(&threadControl->thread_id[i], NULL, worker, (void *)threadControl);
    }

    return 0;
}

int initSockBindListen(int *listenFd, char *ip, int port)
{
    // printf("ip:%s\tport:%d\n",ip,port);
    *listenFd = socket(AF_INET, SOCK_STREAM, 0);
    int reuse = 1;
    setsockopt(*listenFd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    ERROR_CHECK(*listenFd, -1, "socket");
    struct sockaddr_in addr_in4;
    addr_in4.sin_family = AF_INET;
    addr_in4.sin_addr.s_addr = inet_addr(ip);
    addr_in4.sin_port = htons(port);
    int ret = bind(*listenFd, (struct sockaddr *)&addr_in4, sizeof(addr_in4));
    ERROR_CHECK(ret, -1, "bind");
    ret = listen(*listenFd, 5);
    ERROR_CHECK(ret, -1, "listen");
    return 0;
}

int getSocktLink(int listen_fd, int *socket_fd)
{
    // 获取连接
    struct sockaddr_in addr_client; // 获取连上来的客户端ip和端口
    memset(&addr_client, 0, sizeof(addr_client));
    socklen_t addr_len = sizeof(addr_client);
    *socket_fd = accept(listen_fd, (struct sockaddr *)&addr_client, &addr_len);
    return 1;
}

int addEpollObj(int epollFd, int fd)
{
    struct epoll_event event;
    memset(&event, 0, sizeof(event));
    event.data.fd = fd;
    event.events = EPOLLIN;
    epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &event);
    return 0;
}

int getAbsPath(qNode_st *node, char *absPath)
{
    // char path[1024] = {0};
    sprintf(absPath, "%s/%s%s", SERVER_PATH, node->username, node->curPath);
    return 1;
}

int handle_client_request(qNode_st *conn, splictDataCarrier_st *splictDataCarrier)
{
    char buffer[1024] = {0};
    // 等待客户端发来的数据载体...
    int ret = recv(conn->fd, buffer, sizeof(buffer), 0);
    if (ret == 0)
        return 0;
    // 判断C与S是否断开连接
    if (ret <= 0)
    {
        if (ret == 0)
        {
            printf("Client disconnected.\n");
        }
        else
        {
            perror("recv");
        }
        conn->aliveStatus = 0;
        close(conn->fd);
        return 0;
    }

    uint32_t cmd_len;
    uint32_t name_len;
    uint32_t path_len;
    memcpy(&cmd_len, buffer, 4);
    cmd_len = ntohl(cmd_len);
    memcpy(&name_len, buffer + 4 + cmd_len, 4);
    name_len = ntohl(name_len);
    memcpy(&path_len, buffer + 8 + cmd_len + name_len, 4);
    path_len = ntohl(path_len);

    char command[256] = {0};
    char user_name[256] = {0};
    char virtual_path[256] = {0};
    char additional[256] = {0};

    memcpy(command, buffer + 4, cmd_len);
    memcpy(user_name, buffer + 8 + cmd_len, name_len);
    memcpy(virtual_path, buffer + 12 + cmd_len + name_len, path_len);

    if (ret > 12 + cmd_len + name_len + path_len)
    {
        uint32_t additional_len;
        memcpy(&additional_len, buffer + 12 + cmd_len + name_len + path_len, 4);
        additional_len = ntohl(additional_len);
        memcpy(additional, buffer + 16 + cmd_len + name_len + path_len, additional_len);
    }
    // printf("Received command: %s\n", command); // 命令全路径

    // printf("//////////////123///////////////Received command: %s\n", command); // 命令全路径
    // printf("Received user_nam: %s\n", user_name);
    // printf("Virtual path: %s\n", virtual_path);
    // printf("Additional info: %s\n", additional);
    // printf("///////127/////////:%s\n",command);
    // memset(splictDataCarrier, 0, sizeof(splictDataCarrier));
    memcpy(splictDataCarrier->command, command, strlen(command));
    memcpy(splictDataCarrier->username, user_name, strlen(user_name));
    memcpy(splictDataCarrier->virtual_path, virtual_path, strlen(virtual_path));
    memcpy(splictDataCarrier->additional, additional, strlen(additional));
    // printf("///////132/////////:%s\n",splictDataCarrier->command);
    return 1;
}

void *worker(void *args)
{
    status_st *threadControl = (status_st *)args;
    queue_st *q = &threadControl->q;
    int socketFd;
    while (1)
    {
        // 从队列中取一个对象出来
        // 加锁
        pthread_mutex_lock(&threadControl->mutex);

        while (isEmpty(q) == true)
        {
            // 阻塞
            // printf("进入阻塞...\n");
            pthread_cond_wait(&threadControl->cond, &threadControl->mutex);
            if (threadControl->exitFlag == -1)
            {
                pthread_mutex_unlock(&threadControl->mutex);
                pthread_exit(NULL);
            }
        }
        logWrite(NULL,"解锁..\n");
        //  printf(" worker3 \n");
        // 取出元素
        qNode_st *node = deQueue(q);

        socketFd = node->fd;
        printf("socketFd:%d\n",socketFd);
        node->aliveStatus = 1;
        // 唤醒生产者
        pthread_cond_signal(&threadControl->cond);
        // 解锁
        pthread_mutex_unlock(&threadControl->mutex);

        // sleep(10);
        // TODO...做事中
        char recv_buf[1024];
        char send_buf[1024];
        while (1)
        {
            memset(recv_buf, 0, sizeof(recv_buf));
            memset(send_buf, 0, sizeof(send_buf));

            // 对客户端发送过来的数据载体进行解析，里面有等待
            splictDataCarrier_st splictDataCarrier;
            memset(&splictDataCarrier, 0, sizeof(splictDataCarrier));
            memcpy(splictDataCarrier.serverPath, node->serverPath, strlen(node->serverPath));
            splictDataCarrier.socketFd = node->fd; // 将文件描述符发给函数
            printf("////等待客户端发送命令////\n");
            int ret = handle_client_request(node, &splictDataCarrier);
            if (ret == 0)
            {
                printf("客户端断开...\n");
                logWrite(NULL,"客户端断开...\n");
                break;
            }

            // 切分命令【如:得到ls cd mkdir】
            char command[10] = {0};
            memcpy(command, splictDataCarrier.command, strlen(splictDataCarrier.command));
            char *cmd = strtok(command, " ");
            // printf("cmd:%s\n", cmd);
            if (strcmp(cmd, "cd") == 0)
            {
                printf("处理cd命令..\n");
                logWrite(NULL,"处理cd命令..\n");
                int len = 0;
                char **tokens = splitString(splictDataCarrier.command, " /", &len);
                char absPath[1024] = {0};
                getServerAbsPath(&splictDataCarrier, absPath);
                // printf("212:absPath:%s\n", absPath);

                char cur[1024] = {0};
                memset(cur, 0, sizeof(cur));
                // 客户端在服务器的绝对路径
                if (strlen(splictDataCarrier.virtual_path) != 1)
                {
                    sprintf(cur, "%s/%s%s", splictDataCarrier.serverPath,
                            splictDataCarrier.username, splictDataCarrier.virtual_path);
                }
                else
                {
                    sprintf(cur, "%s/%s", splictDataCarrier.serverPath,
                            splictDataCarrier.username);
                }

                cdFunc(&splictDataCarrier, tokens, cur, splictDataCarrier.virtual_path, node->fd, len);
            }
            else if (strcmp(cmd, "ls") == 0)
            {
                printf("处理ls命令..\n");
                logWrite(NULL,"处理ls命令..\n");
                /*-----------测试数据-----------*/
                // 当前用户所在工作目录
                // char *curDir = "/home/tsang/srcode/group_project";
                // 命令行中指定的路径参数
                // char *path = "/client";
                /*-----------测试数据-----------*/

                // printf("unitest_lsCmdSimulation(&splictDataCarrier)执行开始\n");
                // unitest_lsCmdSimulation(&splictDataCarrier);
                // printf("unitest_lsCmdSimulation(&splictDataCarrier)执行完毕\n");
                lsCmdHandle(&splictDataCarrier);
            }
            else if (strcmp(command, "puts") == 0)
            {
                printf("处理puts命令..\n");
                logWrite(NULL,"处理puts命令..\n");
                char cur[1024] = {0};
                memset(cur, 0, sizeof(cur));
                // 客户端在服务器的绝对路径
                if (strlen(splictDataCarrier.virtual_path) != 1)
                {
                    sprintf(cur, "%s/%s%s", splictDataCarrier.serverPath,
                            splictDataCarrier.username, splictDataCarrier.virtual_path);
                }
                else
                {
                    sprintf(cur, "%s/%s", splictDataCarrier.serverPath,
                            splictDataCarrier.username);
                }

                int len = 0;
                char **tokens = splitString(splictDataCarrier.command, " /", &len);
                char absPath[1024] = {0};
                memset(absPath, 0, sizeof(absPath));
                // printf("len:%d\n", len);
                // for (int i = 0; i < len; i++)
                // {
                //     printf("%s\n", tokens[i]);
                // }
                bool isFlag = getServerAbsPath(&splictDataCarrier, absPath);
                if (isFlag == false)
                // printf("212:absPath:%s\n", absPath);
                // printf("len:%d\n", len);
                // for (int i = 0; i < len; i++)
                // {
                //     printf("%s\n", tokens[i]);
                // }
                putsFunc(tokens, absPath, cur, node->fd, len);
            }
            else if (strcmp(cmd, "gets") == 0)
            {
                printf("处理gets命令..\n");
                logWrite(NULL,"处理gets命令..\n");
                sHandleGets(&splictDataCarrier);
                // printf("server中gets处理完毕..\n");
                continue;
            }
            else if (strcmp(cmd, "remove") == 0)
            {
                printf("处理remove命令..\n");
                logWrite(NULL,"处理remove命令..\n");
                removeFunc(&splictDataCarrier);
                // printf("server中remove处理完毕..\n");
                continue;
            }
            else if (strcmp(cmd, "pwd") == 0)
            {
                printf("处理pwd命令..\n");
                logWrite(NULL,"处理pwd命令..\n");
            }
            else if (strcmp(cmd, "mkdir") == 0)
            {
                printf("处理mkdir命令..\n");
                logWrite(NULL,"处理mkdir命令..\n");
                
                int len = 0;
                char **tokens = splitString(splictDataCarrier.command, " /", &len);
                char absPath[1024] = {0};
                memset(absPath, 0, sizeof(absPath));
                // printf("len:%d\n", len);
                // 客户端在服务器的绝对路径
                if (strlen(splictDataCarrier.virtual_path) != 1)
                {
                    sprintf(absPath, "%s/%s%s", splictDataCarrier.serverPath,
                            splictDataCarrier.username, splictDataCarrier.virtual_path);
                }
                else
                {
                    sprintf(absPath, "%s/%s", splictDataCarrier.serverPath,
                            splictDataCarrier.username);
                }

                // printf("212:absPath:%s\n", absPath);
                // printf("len:%d\n", len);
                // for (int i = 0; i < len; i++)
                // {
                //     printf("%s\n", tokens[i]);
                // }
                mkdirFunc(tokens, absPath, node->fd, len);
            }
            else
            {
                printf("无效命令..\n");
                logWrite("error","无效命令..\n");
                continue;
            }
        }
        printf("进程退出124\n");
        logWrite(NULL,"进程退出124\n");
        if (threadControl->exitFlag == -1)
        {
            pthread_mutex_unlock(&threadControl->mutex);
            pthread_exit(NULL);
        }
    }

    return NULL;
}
